local skynet = require "skynet"
local table_insert = table.insert
local table_remove = table.remove
local msghelper = require "tablehelper"
local timetool = require "timetool"
local tabletool = require "tabletool"
local timer = require "timer"
local filelog = require "filelog"
local json = require "cjson"
json.encode_sparse_array(true,1,1)
require "dzpkenum"
local texascard = require "texascard"

local tablelogic
local seatlogic
local server
local table_data

local GameLogic = {}

function GameLogic.init(tablebase)
	server = tablebase
	table_data = server.table_data
	tablelogic = tablebase.logic.tablelogic
	seatlogic  = tablebase.logic.seatlogic
	return true
end

function GameLogic.gamestart()
	GameLogic.onegamestart_inittable()

	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			seatlogic.onegamestart_initseat(seat)
        end
	end
	local gamestartntcmsg = {}
	gamestartntcmsg.gameinfo = {}
	msghelper:copy_table_gameinfo(gamestartntcmsg.gameinfo)
	msghelper:sendmsg_to_alltableplayer("gamestartN", gamestartntcmsg)
	-- 洗牌
	GameLogic.riffleandpostcards()
end

function GameLogic.onegamestart_inittable()
	table_data.state = ETableState.TABLE_STATE_GAME_START
	table_data.action_seat_index = 0
	table_data.action_to_time = 0
	table_data.action_type = 0
	table_data.initcards = {}		-- 牌池
	table_data.pubcards = {}		-- 公共牌
	table_data.tmpdiamond = {}
	table_data.gamerecords = {}
	table_data.recycled = nil
	table_data.passiveleaveall = nil
	table_data.banker_index = nil
	table_data.small_blinds_index = nil
	table_data.big_blinds_index = nil
	table_data.small_blinds_done = nil
	table_data.big_blinds_done = nil
	table_data.round_begin_index = nil
	table_data.winseats = {}
	table_data.compared = nil
	table_data.allbets = 0
	table_data.betcount = 1
	table_data.highest_chip = 0
	table_data.last_raise_diff = 0
	table_data.sidepool = {}
	table_data.allindata = {}
	if table_data.timer_id and table_data.timer_id > 0 then
		timer.cleartimer(table_data.timer_id)
		table_data.timer_id = -1
	end
end

local function find_next_index(seat_index)
	local seatindex = seat_index or 1
	repeat
		seatindex = seatindex + 1
		if seatindex > #table_data.seats then
			seatindex = 1
		end
		local seat = table_data.seats[seatindex]
		if seatindex ~= seat_index then
			if seat.state == ESeatState.SEAT_STATE_PLAYING then
				return seatindex
			end
		end
	until seatindex == seat_index
end

local function find_pre_index(seat_index)
	local seatindex = seat_index or 1
	repeat
		seatindex = seatindex - 1
		if seatindex <= 0 then
			seatindex = #table_data.seats
		end
		local seat = table_data.seats[seatindex]
		if seatindex ~= seat_index then
			if seat.state == ESeatState.SEAT_STATE_PLAYING or seat.state == ESeatState.SEAT_STATE_ALL_IN then
				return seatindex
			end
		end
	until seatindex == seat_index
end

--找到小盲位置
function GameLogic.find_smallblinds_index()
	for i = 1, #table_data.seats - 1 do
		local next_index = (table_data.banker_index + i) % 9
		if next_index == 0 then
			next_index = 9
		end
		if table_data.seats[next_index].state == ESeatState.SEAT_STATE_PLAYING then
			return next_index
		end
    end
end

--找到大盲位置
function GameLogic.find_bigblinds_index()
	for i = 1, #table_data.seats - 1 do
		local next_index = (table_data.small_blinds_index + i) % 9
		if next_index == 0 then
			next_index = 9
		end
		if table_data.seats[next_index].state == ESeatState.SEAT_STATE_PLAYING then
			return next_index
		end
    end
end

function GameLogic.riffleandpostcards()
	local now = timetool.get_time()
	-- 生成一副牌 洗牌
	texascard.cards_shuffle(table_data.initcards)
	if table_data.dealer then
		table_data.banker_index = find_next_index(table_data.dealer)
	else
		table_data.banker_index = math.random(table_data.playernum)
	end
	table_data.dealer = table_data.banker_index
	msghelper:sendmsg_to_alltableplayer("dealerN", {
		seat_index = table_data.dealer,
	})

	table_data.gamerecords.initcards = json.encode(table_data.initcards)

	-- 确定大小盲注位置
    if table_data.playernum == 2 then
        table_data.small_blinds_index = table_data.banker_index
        table_data.big_blinds_index = GameLogic.find_bigblinds_index()
    else
        table_data.small_blinds_index = GameLogic.find_smallblinds_index()
        table_data.big_blinds_index = GameLogic.find_bigblinds_index()
    end

	table_data.state = ETableState.TABLE_STATE_ACTION
	filelog.debug("blind index:", table_data.small_blinds_index, table_data.big_blinds_index)
	-- 先小盲注
	GameLogic.actions[EActionType.ACTION_TYPE_BLIND_BET1](table_data.seats[table_data.small_blinds_index])
	-- 再大盲注
	GameLogic.actions[EActionType.ACTION_TYPE_BLIND_BET2](table_data.seats[table_data.big_blinds_index])

	-- 给玩家发手牌 Perflop
    for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
            table_insert(seat.cards, table_remove(table_data.initcards, 1))
			table_insert(seat.cards, table_remove(table_data.initcards, 1))
			msghelper:sendmsg_to_tableplayer(seat, "cardinfoN", {
				cards = seat.cards,
			})
        end
	end

	table_data.timer_id = timer.settimer(1*100, "firsttodo")

	local handcards = {}
	local rids = {}
	local playerdata = {}
	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER and seat.state ~= ESeatState.SEAT_STATE_WATCHING then
			handcards[seat.rid] = tabletool.deepcopy(seat.cards)
			table.insert(rids, seat.rid)
			playerdata[seat.rid] = {
				name = seat.playerinfo.rolename,
				logo = seat.playerinfo.logo,
				sex = seat.playerinfo.sex,
				diamond = seat.diamond,
			}
		end
	end

	if table_data.conf.room_type ~= ERoomType.ROOM_TYPE_SYSTEM then
		table.sort(rids, function(l, r)
			return l < r
		end)
		local ridsstr = ''
		for _, rid in ipairs(rids) do
			if ridsstr == '' then
				ridsstr = ridsstr .. rid
			else
				ridsstr = ridsstr .. '_' .. rid
			end
		end
		-- init gamerecords
		table_data.gamerecords.start_time = now
		table_data.gamerecords.table_uuid = skynet.getenv("nodename") .. "_"
			.. table_data.conf.table_code .. "_"
			.. table_data.conf.idx .. "_" .. table_data.conf.create_time
		table_data.gamerecords.logname = '' .. table_data.gamerecords.table_uuid .. '_'
			.. now .. '_' .. '0' .. '_'
			.. ridsstr .. '_' .. os.date("%Y%m%d_%H%M%S", now) .. '_'
			.. table_data.conf.game_room_type
		table_data.gamerecords.handcards = json.encode(handcards)
		table_data.gamerecords.rids = ridsstr
		table_data.gamerecords.playerdata = json.encode(playerdata)
	end

	table_data.conf.curr_round_code = string.sub(tostring(now), -4, -1)
	if table_data.conf.room_type ~= ERoomType.ROOM_TYPE_SYSTEM then
		table_data.gamerecords.conf = json.encode(table_data.conf)
		tablelogic.save_actions(table_data)
	end
end

function GameLogic.gameover()
	table_data.round_begin_index = nil
	table_data.state = ETableState.TABLE_STATE_GAME_OVER

	-- 奖池分钱处理
	local baseval = 0
	local index = 0
	local winrid = nil
	if #table_data.sidepool > 0 then
		for i, seat in ipairs(table_data.seats) do
			if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER and seat.state ~= ESeatState.ACTION_TYPE_FOLD then
				-- 玩家不参与结算的话不考虑
				texascard.analyse(table_data, i)
			end
		end
		for _, pool in ipairs(table_data.sidepool) do
			if #pool.indexes > 0 then
				local poolwinseats = {}
				index = pool.indexes[1]
				poolwinseats[1] = table_data.seats[index]
				for i, idx in ipairs(pool.indexes) do
					if i ~= 1 then
						index = pool.indexes[i]
						local result = texascard.priocompare(poolwinseats[1], table_data.seats[index])
						if result < 0 then
							poolwinseats = {}
							poolwinseats[1] = table_data.seats[index]
						elseif result == 0 then
							-- 平局处理
							poolwinseats[#poolwinseats + 1] = table_data.seats[index]
						end
					end
				end
				local num = #poolwinseats
				if num == 1 then
					tablelogic.change_money(table_data, poolwinseats[1], pool.bets, true)
					winrid =  poolwinseats[1].rid
				elseif num > 1 then
					local averageval = math.floor(pool.bets / num)
					for i, v in ipairs(poolwinseats) do
						if i == 1 then
							tablelogic.change_money(table_data, v, pool.bets - averageval*(num - 1), true)
						else
							tablelogic.change_money(table_data, v, averageval, true)
						end
					end
				end
			end
		end
	else
		baseval = table_data.allbets
		local winseats = table_data.winseats
		local winnum = #winseats
		if winnum == 1 then
			tablelogic.change_money(table_data, winseats[1], baseval, true)
			winrid =  winseats[1].rid
		elseif winnum > 1 then
			local averageval = math.floor(baseval / winnum)
			for i, v in ipairs(winseats) do
				if i == 1 then
					tablelogic.change_money(table_data, v, baseval - averageval*(winnum - 1), true)
				else
					tablelogic.change_money(table_data, v, averageval, true)
				end
			end
		end
	end

	local balancedata = {playerdata = {}}
	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			tablelogic.pay_money(table_data, seat)
			local pdata = {}
			pdata.rid = seat.rid
			pdata.seat_index = seat.index
			pdata.balance_val = table_data.tmpdiamond[seat.rid].value
			pdata.diamond = table_data.tmpdiamond[seat.rid].endvalue
			if table_data.compared then
				pdata.card = seat.cards
			end
			table_insert(balancedata.playerdata, pdata)
		end
	end
	tablelogic.change_all_player_money(table_data)
	if table_data.compared then
		balancedata.pubcards = table_data.pubcards
		balancedata.winrid = winrid
	end
	filelog.trace("balancN data:", balancedata)
	msghelper:sendmsg_to_alltableplayer("balanceN", balancedata)

	table_data.timer_id = timer.settimer(5*100, "showbalanceover")
end

function GameLogic.todonotice()
	filelog.warn("todoaction:action_seat_index = ", table_data.action_seat_index)
	msghelper:sendmsg_to_alltableplayer("todoN", {
		rid = table_data.seats[table_data.action_seat_index].rid,
		seat_index = table_data.action_seat_index,
		action_to_time = timetool.get_time() + table_data.conf.action_timeout,
		highest_chip = table_data.highest_bet,
		last_raise_diff = table_data.last_raise_diff,
		curr_chip = table_data.seats[table_data.action_seat_index].curr_bets,
	})
end

-- all in对奖池的影响，配合每一次操作对奖池的影响，这种方式需要改结算处理
local function makebetspool(allinseat)
	local calseats = {}
	for _, seat in ipairs(table_data.seats) do
		if (seat.curr_bets > 0) and ((seat.state == ESeatState.SEAT_STATE_PLAYING) or (seat.state == ESeatState.SEAT_STATE_ALL_IN)) then
			table_insert(calseats, {index = seat.index, curr_bets = seat.curr_bets})
		end
	end

	local pools = {}
	local pool = {bets = 0, indexes = {}, allinbets = 0}
	for _, seat in ipairs(calseats) do	-- 还要根据当前已有的边池做扣除，这里还未实现!!!
		if seat.curr_bets > 0 then
			pool.indexes[seat.index] = v.allinbets
			if seat.curr_bets > v.allinbets then
				pool.bets = pool.bets + v.allinbets
				seat.curr_bets = seat.curr_bets - v.allinbets
			else
				pool.bets = pool.bets + seat.curr_bets
				seat.curr_bets = 0
			end
		end
	end
	table_insert(pools, pool)

	local tmppool = {bets = 0, indexes = {}, allinbets = allinseat.curr_bets}
	for _, seat in ipairs(calseats) do
		if seat.curr_bets > 0 then
			tmppool.indexes[seat.index] = seat.curr_bets
			tmppool.bets = tmppool.bets + seat.curr_bets
		end
	end
	if tmppool.bets > 0 then
		table_insert(pools, tmppool)
	end

	for i, v in ipairs(pools) do
		if #table_data.sidepool > 0 then
			if i == 1 then
				table_data.sidepool[#table_data.sidepool].bets = table_data.sidepool[#table_data.sidepool].bets + v.bets
			else
				table_insert(table_data.sidepool, v)
			end
		else
			table_insert(table_data.sidepool, v)
		end
	end

	local betspools = {}
	for _, v in ipairs(table_data.sidepool) do
		table_insert(betspools, v.bets)
	end
	if #table_data.sidepool > 0 then
		msghelper:sendmsg_to_alltableplayer("chipspoolsN", {
			chipspools = betspools,
		})
	end
end

-- 每一次操作对奖池的影响
local function addtobetspool(seat)
	if #table_data.sidepool == 0 then return end
	local len = #table_data.sidepool
	local pool = table_data.sidepool[len]
	local prepool = table_data.sidepool[len - 1]
	if pool then
		if prepool then	-- 不止prepool，还需要往前找完全部，这里还未实现!!!
			local lastval = seat.curr_bets
			for i, prepool in ipairs(table_data.sidepool) do
				if i ~= len then
					if prepool.indexes[seat.index] then
						prepool.bets = prepool.bets - prepool.indexes[seat.index]
						prepool.bets = prepool.bets + prepool.allinbets
						lastval = lastval - prepool.allinbets
					end
				end
			end
			if pool.indexes[seat.index] then
				pool.bets = pool.bets - pool.indexes[seat.index]
			else
				pool.indexes[seat.index] = lastval
			end
			pool.bets = pool.bets + lastval
		else
			if seat.curr_bets > pool.allinbets then
				if pool.indexes[seat.index] then
					pool.bets = pool.bets - pool.indexes[seat.index]
					pool.bets = pool.bets + pool.allinbets
				end
				local newpool = {bets = seat.curr_bets - pool.allinbets, indexes = {}, allinbets = pool.allinbets}
				newpool.indexes[seat.index] = newpool.bets
				table_data.sidepool[len + 1] = newpool
			else
				if pool.indexes[seat.index] then
					pool.bets = pool.bets - pool.indexes[seat.index]
				end
				pool.bets = pool.bets + seat.curr_bets
			end
		end
	end
	local betspools = {}
	for _, v in ipairs(table_data.sidepool) do
		table_insert(betspools, v.bets)
	end
	if #table_data.sidepool > 0 then
		msghelper:sendmsg_to_alltableplayer("chipspoolsN", {
			chipspools = betspools,
		})
	end
end

-- 一轮结束后奖池的计算
local function calbetspool()
	local calseats = {}
	for _, seat in ipairs(table_data.seats) do
		if (seat.curr_bets > 0) and ((seat.state == ESeatState.SEAT_STATE_PLAYING) or (seat.state == ESeatState.SEAT_STATE_ALL_IN)) then
			table_insert(calseats, {index = seat.index, curr_bets = seat.curr_bets})
		end
	end
	local sidepools = {}
	table.sort(table_data.allindata, function(l, r)
		return l.allinbets < r.allinbets
	end)
	for i, v in ipairs(table_data.allindata) do -- i = 1 即为这一轮的底池，需要和上一轮的最后一个边池合并
		sidepools[i] = {bets = 0, indexes = {}}
		for _, seat in ipairs(calseats) do
			table_insert(sidepools[i].indexes, seat.index)
			if seat.curr_bets > v.allinbets then
				sidepools[i].bets = sidepools[i].bets + v.allinbets
				seat.curr_bets = seat.curr_bets - v.allinbets
			else
				sidepools[i].bets = sidepools[i].bets + seat.curr_bets
				seat.curr_bets = 0
			end
		end
	end

	local tmppool = {bets = 0, indexes = {}}
	for _, seat in ipairs(calseats) do
		table_insert(tmppool.indexes, seat.index)
		tmppool.bets = tmppool.bets + seat.curr_bets
	end
	if tmppool.bets > 0 then
		table_insert(sidepools, tmppool)
	end

	for i, v in ipairs(sidepools) do
		if #table_data.sidepool > 0 then
			if i == 1 then
				table_data.sidepool[#table_data.sidepool].bets = table_data.sidepool[#table_data.sidepool].bets + v.bets
			else
				table_insert(table_data.sidepool, v)
			end
		else
			table_insert(table_data.sidepool, v)
		end
	end
	filelog.trace("round_" .. table_data.betcount .. " sidepool = ", table_data.sidepool)
	local betspools = {}
	for _, v in ipairs(table_data.sidepool) do
		table_insert(betspools, v.bets)
	end
	if #table_data.sidepool > 0 then
		msghelper:sendmsg_to_alltableplayer("chipspoolsN", {
			chipspools = betspools,
		})
	end
end

local function compare()
	local winseats = {}
	for i, seat in ipairs(table_data.seats) do
		if seat.state == ESeatState.SEAT_STATE_PLAYING or seat.state == ESeatState.SEAT_STATE_ALL_IN then
			if winseats[1] == nil then
				winseats[1] = seat
			end
			-- 没下注的不考虑 && 玩家不参与结算的话不考虑
			texascard.analyse(table_data, i)
		end
	end
	for _, seat in ipairs(table_data.seats) do
		if (seat.state == ESeatState.SEAT_STATE_PLAYING or seat.state == ESeatState.SEAT_STATE_ALL_IN) and seat.index ~= winseats[1].index then
			local result = texascard.priocompare(winseats[1], seat)
			if result < 0 then
				winseats = {}
				winseats[1] = seat
			elseif result == 0 then
				-- 平局处理
				winseats[#winseats + 1] = seat
			end
		end
	end
	table_data.winseats = winseats
	table_data.compared = true
end

local function check_gameover()
	local lastnum = 0
	for _, seat in ipairs(table_data.seats) do
		if seat.state == ESeatState.SEAT_STATE_PLAYING or seat.state == ESeatState.SEAT_STATE_ALL_IN then
			lastnum = lastnum + 1
			table_data.winseats[1] = seat
		end
	end
	if lastnum <= 1 then
		GameLogic.gameover()
		return true
	end
	table_data.winseats = {}
	return false
end

local function round_over(next_index)
	local count = table_data.betcount
	calbetspool()
	if count == 1 then	-- 翻牌前下注结束
		table_remove(table_data.initcards, 1)
		for i = 1, 3 do
			table_insert(table_data.pubcards, table_remove(table_data.initcards, 1))
		end
		msghelper:sendmsg_to_alltableplayer("pubcardsflopN", {
			cards = table_data.pubcards,
		})
		table_data.round_begin_index = table_data.banker_index
		table_data.state = ETableState.TABLE_STATE_ACTION
	elseif count == 2 then	-- 翻牌圈下注结束
		table_remove(table_data.initcards, 1)
		table_insert(table_data.pubcards, table_remove(table_data.initcards, 1))
		msghelper:sendmsg_to_alltableplayer("pubcardsturnN", {
			cards = {table_data.pubcards[4]},
		})
		table_data.round_begin_index = next_index
		table_data.state = ETableState.TABLE_STATE_ACTION
	elseif count == 3 then	-- 转牌圈下注结束
		table_remove(table_data.initcards, 1)
		table_insert(table_data.pubcards, table_remove(table_data.initcards, 1))
		msghelper:sendmsg_to_alltableplayer("pubcardsriverN", {
			cards = {table_data.pubcards[5]},
		})
		table_data.round_begin_index = next_index
		table_data.state = ETableState.TABLE_STATE_ACTION
	else					-- 河牌圈下注结束
		table_data.round_begin_index = nil
		table_data.state = ETableState.TABLE_STATE_COMPARE
		
		-- 比牌
		compare()
		-- 本局结束
		GameLogic.gameover()
		return
	end

	local num = 0
	for _, seat in ipairs(table_data.seats) do
		if seat.state == ESeatState.SEAT_STATE_PLAYING then
			num = num + 1
        end
	end
	if num == 1 then
		if count == 2 then	-- 翻牌圈下注结束
			table_remove(table_data.initcards, 1)
			table_insert(table_data.pubcards, table_remove(table_data.initcards, 1))
			msghelper:sendmsg_to_alltableplayer("pubcardsturnN", {
				cards = {table_data.pubcards[4]},
			})
			
			table_remove(table_data.initcards, 1)
			table_insert(table_data.pubcards, table_remove(table_data.initcards, 1))
			msghelper:sendmsg_to_alltableplayer("pubcardsriverN", {
				cards = {table_data.pubcards[5]},
			})
		elseif count == 3 then	-- 转牌圈下注结束
			table_remove(table_data.initcards, 1)
			table_insert(table_data.pubcards, table_remove(table_data.initcards, 1))
			msghelper:sendmsg_to_alltableplayer("pubcardsriverN", {
				cards = {table_data.pubcards[5]},
			})
		end
		-- 比牌
		compare()
		-- 本局结束
		GameLogic.gameover()
		return
	end

	table_data.betcount = table_data.betcount + 1

	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			seat.curr_bets = 0
        end
	end
	table_data.highest_bet = 0
	table_data.raise_diff = 0
	table_data.allindata = {}

	if table_data.state == ETableState.TABLE_STATE_ACTION then
		table_data.action_seat_index = table_data.round_begin_index
		skynet.sleep(2*100)
		if table_data.state == ETableState.TABLE_STATE_ACTION then
			GameLogic.todonotice()
		end
	end
end

GameLogic.actions = {
	[EActionType.ACTION_TYPE_BLIND_BET1] = function(seat, param)	-- [1] 小盲注
		if seat.index == table_data.small_blinds_index then
			if not table_data.small_blinds_done then
				table_data.small_blinds_done = 1
			else
				return false
			end
		else
			return false
		end
		local blindbet = table_data.conf.base_score
		if seat.diamond < blindbet then return false end
		tablelogic.change_money(table_data, seat, -blindbet)
		--更新最高下注
		table_data.highest_bet = blindbet
		--更新加注额
		table_data.last_raise_diff = blindbet

		msghelper:sendmsg_to_alltableplayer("doactionN", {
			rid = seat.rid,
			seat_index = seat.index,
			action_type = EActionType.ACTION_TYPE_BLIND_BET1,
			round = 0,
			chip = blindbet,
		})
		return true
	end,
	[EActionType.ACTION_TYPE_BLIND_BET2] = function(seat, param)	-- [2] 大盲注
		if seat.index == table_data.big_blinds_index then
			if not table_data.big_blinds_done then
				table_data.big_blinds_done = 1
			else
				return false
			end
		else
			return false
		end
		local blindbet = table_data.conf.base_score * 2
		if seat.diamond < blindbet then return false end
		tablelogic.change_money(table_data, seat, -blindbet)
		--更新最高下注
		table_data.highest_bet = blindbet
		--更新加注额
		table_data.last_raise_diff = blindbet

		msghelper:sendmsg_to_alltableplayer("doactionN", {
			rid = seat.rid,
			seat_index = seat.index,
			action_type = EActionType.ACTION_TYPE_BLIND_BET2,
			round = 0,
			chip = blindbet,
		})
		if table_data.playernum == 2 then
			table_data.action_seat_index = table_data.small_blinds_index
		else
			table_data.action_seat_index = find_next_index(table_data.big_blinds_index)
		end
		table_data.round_begin_index = table_data.action_seat_index
		return true
	end,
	[EActionType.ACTION_TYPE_BET] = function(seat, param)	-- [3] 下注
		param = table_data.highest_bet
		if seat.diamond < param then return false end
		tablelogic.change_money(table_data, seat, -param)
		table_data.round_begin_index = table_data.action_seat_index

		table_data.highest_bet = seat.curr_bets
		table_data.last_raise_diff = param
		msghelper:sendmsg_to_alltableplayer("doactionN", {
			rid = seat.rid,
			seat_index = seat.index,
			action_type = EActionType.ACTION_TYPE_BET,
			round = table_data.betcount,
			chip = param,
		})

		local next_index = find_next_index(table_data.action_seat_index)
		if next_index == table_data.round_begin_index then
			table_data.state = ETableState.TABLE_STATE_WAIT
			round_over(next_index)
		else
			table_data.action_seat_index = next_index
			GameLogic.todonotice()
		end
		return true
	end,
	[EActionType.ACTION_TYPE_CALL] = function(seat, param)	-- [4] 跟注
		param = seat.curr_bets - table_data.highest_bet
		if seat.curr_bets < table_data.highest_bet then
			if seat.diamond < -param then return false end
			tablelogic.change_money(table_data, seat, param)

			local preseat = table_data.seats[find_pre_index(seat.index)]
			if preseat.state == ESeatState.SEAT_STATE_ALL_IN then
				table_data.round_begin_index = table_data.action_seat_index
			end
		end

		-- 必须在change_money后
		msghelper:sendmsg_to_alltableplayer("doactionN", {
			rid = seat.rid,
			seat_index = seat.index,
			action_type = EActionType.ACTION_TYPE_CALL,
			round = table_data.betcount,
			chip = param < 0 and -param or param,
		})

		local next_index = find_next_index(table_data.action_seat_index)
		if next_index == table_data.round_begin_index then
			table_data.state = ETableState.TABLE_STATE_WAIT
			round_over(next_index)
		else
			table_data.action_seat_index = next_index
			GameLogic.todonotice()
		end
		return true
	end,
	[EActionType.ACTION_TYPE_RAISE] = function(seat, param)	-- [5] 加注
		if not param or param < 0 then return false end
		-- check param
		if param < table_data.highest_bet + table_data.last_raise_diff - seat.curr_bets then return false end
		if seat.diamond < param then return false end
		tablelogic.change_money(table_data, seat, -param)
		
		table_data.last_raise_diff = seat.curr_bets - table_data.highest_bet
		table_data.highest_bet = seat.curr_bets
		table_data.round_begin_index = table_data.action_seat_index
		
		msghelper:sendmsg_to_alltableplayer("doactionN", {
			rid = seat.rid,
			seat_index = seat.index,
			action_type = EActionType.ACTION_TYPE_RAISE,
			round = table_data.betcount,
			chip = param,
		})
		
		local next_index = find_next_index(table_data.action_seat_index)
		if next_index == table_data.round_begin_index then
			table_data.state = ETableState.TABLE_STATE_WAIT
			round_over(next_index)
		else
			table_data.action_seat_index = next_index
			GameLogic.todonotice()
		end
		return true
	end,
	[EActionType.ACTION_TYPE_ALL_IN] = function(seat, param)	-- [6] 全下
		param = seat.diamond
		tablelogic.change_money(table_data, seat, -param)
		
		--更新加注额
		local raise_diff = seat.curr_bets - table_data.highest_bet
		if raise_diff < 0 then
			raise_diff = 0
		end
		if raise_diff > table_data.last_raise_diff then
			--更新最高下注
			if seat.curr_bets > table_data.highest_bet then    
				table_data.highest_bet = seat.curr_bets
			end
			table_data.last_raise_diff = raise_diff
		end
		msghelper:sendmsg_to_alltableplayer("doactionN", {
			rid = seat.rid,
			seat_index = seat.index,
			action_type = EActionType.ACTION_TYPE_ALL_IN,
			round = table_data.betcount,
			chip = param,
		})
		
		table_data.allindata = table_data.allindata or {}
		table_insert(table_data.allindata, {betcount = table_data.betcount, allinbets = seat.curr_bets})
		
		seat.state = ESeatState.SEAT_STATE_ALL_IN
		local next_index = find_next_index(table_data.action_seat_index)
		if next_index == table_data.round_begin_index then
			table_data.state = ETableState.TABLE_STATE_WAIT
			round_over(next_index)
		else
			table_data.action_seat_index = next_index
			GameLogic.todonotice()
		end
		return true
	end,
	[EActionType.ACTION_TYPE_CHECK] = function(seat, param)	-- [7] 让牌
		local preseat = table_data.seats[find_pre_index(seat.index)]
		if seat.curr_bets ~= preseat.curr_bets then
			return false
		end
		
		msghelper:sendmsg_to_alltableplayer("doactionN", {
			rid = seat.rid,
			seat_index = seat.index,
			action_type = EActionType.ACTION_TYPE_CHECK,
			round = table_data.betcount,
			chip = 0,
		})
		
		local next_index = find_next_index(table_data.action_seat_index)
		if next_index == table_data.round_begin_index then
			table_data.state = ETableState.TABLE_STATE_WAIT
			round_over(next_index)
		else
			table_data.action_seat_index = next_index
			GameLogic.todonotice()
		end
		return true
	end,
	[EActionType.ACTION_TYPE_FOLD] = function(seat, param)	-- [8] 弃牌
		seat.state = ESeatState.ACTION_TYPE_FOLD

		msghelper:sendmsg_to_alltableplayer("doactionN", {
			rid = seat.rid,
			seat_index = seat.index,
			action_type = EActionType.ACTION_TYPE_FOLD,
			round = table_data.betcount,
			chip = 0,
		})

		if check_gameover() then
			return true
		end
		local next_index = find_next_index(table_data.action_seat_index)
		if next_index == table_data.round_begin_index then
			table_data.state = ETableState.TABLE_STATE_WAIT
			round_over(next_index)
		else
			table_data.action_seat_index = next_index
			GameLogic.todonotice()
			if seat.index == table_data.round_begin_index then
				table_data.round_begin_index = next_index
			end
			if seat.index == table_data.banker_index then
				table_data.banker_index = next_index
			end
		end
		return true
	end,
}

return GameLogic